Skip to content

fix(characters): stop extrapolating a dying entity's movement state into an NPE - #5380

Open
soloturn wants to merge 1 commit into
developfrom
soloturn-char-movement-npe-4969
Open

fix(characters): stop extrapolating a dying entity's movement state into an NPE#5380
soloturn wants to merge 1 commit into
developfrom
soloturn-char-movement-npe-4969

Conversation

@soloturn

Copy link
Copy Markdown
Contributor

AI-assisted change proposal. Filed by agent driven by @soloturn via GDD.

Summary

Fixes #4969 - server crash (NullPointerException in CharacterMovementSystemUtility.extrapolateCharacterMovementComponent) when a character entity dies while another client still has it queued for a state update.

ServerCharacterPredictionSystem.onDestroy (BeforeDeactivateComponent, gated on CharacterMovementComponent/LocationComponent/AliveCharacterComponent) fires as soon as any one of those three components is removed - e.g. an entity losing AliveCharacterComponent mid-death, before the rest of it is torn down. It only queues the entity into characterStatesToRemove rather than removing it from characterStates immediately; that queue is drained once per update() call. In between, restoreToPresent() and lagCompensate() both iterate characterStates unconditionally and can reach setToTime -> setToExtrapolateState -> extrapolateCharacterMovementComponent for an entity whose CharacterMovementComponent is already gone - which unconditionally dereferenced the null getComponent() result, exactly the reported traceback.

Changes

  • restoreToPresent()/lagCompensate() now skip entries already queued in characterStatesToRemove, matching what update()'s own replication loop already did for the same reason.
  • setToExtrapolateState() now checks for both components up front and returns if either is missing, mirroring setToState()'s existing guard in the same class - defense in depth in case some other path reaches it with a torn-down entity.

Test plan

  • New CharacterMovementSystemUtilityTest (3/3 pass): reproduces the exact NPE without the fix, confirms it's gone with it, and confirms a normal (both-components-present) call still updates the entity as before.
  • Existing logic.characters.* unit tests (KinematicCharacterMoverTest, VisualCharacterSystemTest) still pass.

…nto an NPE

Fixes #4969.

ServerCharacterPredictionSystem.onDestroy (BeforeDeactivateComponent, gated
on CharacterMovementComponent/LocationComponent/AliveCharacterComponent)
fires as soon as any one of those three is removed - e.g. an entity losing
AliveCharacterComponent mid-death, before the rest of it is torn down. It
only queues the entity into characterStatesToRemove rather than removing it
from characterStates immediately; that queue is drained once per update()
call. In between, restoreToPresent() and lagCompensate() both iterate
characterStates unconditionally and can call setToTime -> setToExtrapolateState
-> extrapolateCharacterMovementComponent on an entity whose
CharacterMovementComponent is already gone, which unconditionally
dereferenced the null getComponent() result.

Two changes:

- restoreToPresent()/lagCompensate() now skip entries already queued in
  characterStatesToRemove, matching what update()'s own replication loop
  already did for the same reason.
- setToExtrapolateState() now checks for both components up front and
  returns if either is missing, mirroring setToState()'s existing guard
  in the same class - defense in depth in case some other path reaches it
  with a torn-down entity.

Regression test added: CharacterMovementSystemUtilityTest.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@github-actions github-actions Bot added the Type: Bug Issues reporting and PRs fixing problems label Aug 19, 2026
@coderabbitai

coderabbitai Bot commented Aug 19, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: d973c3f6-c818-4905-b079-112850824d00

📥 Commits

Reviewing files that changed from the base of the PR and between 338d7dd and 8cfc61d.

📒 Files selected for processing (3)
  • engine-tests/src/test/java/org/terasology/engine/logic/characters/CharacterMovementSystemUtilityTest.java
  • engine/src/main/java/org/terasology/engine/logic/characters/CharacterMovementSystemUtility.java
  • engine/src/main/java/org/terasology/engine/logic/characters/ServerCharacterPredictionSystem.java

Included review availability: Your plan provides up to 8 included reviews per hour; 7 remain after this review.


📝 Walkthrough

Summary by CodeRabbit

  • Bug Fixes

    • Improved character movement handling when required movement or location data is unavailable.
    • Prevented removed characters from being processed during lag compensation and state restoration.
    • Avoided unnecessary physics interactions and state updates for invalid or queued-for-removal characters.
  • Tests

    • Added coverage for character extrapolation with missing and complete movement data.

Walkthrough

Character movement extrapolation now checks for required components before updating state. Server prediction skips entities queued for deferred removal during lag compensation and state restoration. Regression tests cover missing-component and valid-component behavior.

Changes

Character prediction safeguards

Layer / File(s) Summary
Extrapolation component guards
engine/src/main/java/org/terasology/engine/logic/characters/CharacterMovementSystemUtility.java, engine-tests/src/test/java/org/terasology/engine/logic/characters/CharacterMovementSystemUtilityTest.java
setToExtrapolateState returns without updates when LocationComponent or CharacterMovementComponent is absent. Tests cover missing components and valid component and collider updates.
Deferred removal handling
engine/src/main/java/org/terasology/engine/logic/characters/ServerCharacterPredictionSystem.java
lagCompensate and restoreToPresent skip character states pending removal before accessing components or applying state. Comments document deferred removal processing.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Merge Risk: ⚪ Minimal · up to 8cfc6

The change prevents movement-state processing from dereferencing components that have already been removed during entity teardown, while preserving normal movement updates. No actionable merge-blocking risk remains after normal checks and review.

Poem

I’m a rabbit with a careful stride,
No missing parts are touched inside.
Removed friends wait beyond the queue,
Prediction skips them safely too.
Tests hop through each guarded state.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the character movement extrapolation fix and the resulting NPE prevention.
Description check ✅ Passed The description explains the reported NPE, its cause, the implemented fixes, and regression tests.
Linked Issues check ✅ Passed The changes address issue #4969 by guarding missing components, skipping queued removals, and adding regression tests for the crash.
Out of Scope Changes check ✅ Passed All changes directly support issue #4969 and the stated objectives; no unrelated code changes are identified.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch soloturn-char-movement-npe-4969

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Type: Bug Issues reporting and PRs fixing problems

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

NPE on character movement extrapolation when killing a sheep

2 participants